/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analisador.lexico;

import java.util.ArrayList;

/**
 *
 * @author Danilo
 */

public class AnalisadorSintatico{

    Token token;
    String frase = "", categoria = "";
    boolean erro = false;
    String pre = "";
    String tipoDeclarado;
    String tipoVar;
    String nomeTipoVar;
    ArrayList<Registro> listaVariaveis = new ArrayList<Registro>();
    Registro ultimo;
    boolean declarando = false;
    boolean atribuindo = false;
    String paiImediato;
    boolean ponteiro = false;
    boolean variavel = false;
    boolean duranteRegistro = false;
    boolean tipoNovo = false;    
    boolean parametroFuncao = false;
    boolean chamadaFuncao = false;
    String nomeFuncao;
    String tipoExpressao;
    String tipoParcialExpressao;
    String tipoParcialExpressao2;
    String meuTipo;
    boolean passouOp = false;
    boolean opIgual = false;
    boolean dimensao = false;
    int numeroPai = 0;
    int contador = 0;
    static String msgErro = new String();
    AnalisadorSemantico as = new AnalisadorSemantico();
    private boolean tipoVarPonteiro = false;
    
    public AnalisadorSintatico (Token valor){
        token = valor;
    }


    //Regra 1
    public void programa() throws ExcecaoCompilador {
        token.getToken();
        declaracoes();
        if(token.equals("algoritmo")){
            as.criarEscopo();
            token.getToken();
            corpo();
            //token.getToken();
            if(!token.equals("fim_algoritmo"))
                if (!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a EOF" + "\n";
                    throw new ExcecaoCompilador(frase);//erro
                    //erro = true;
                }
        }else
            if (!erro){
                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                throw new ExcecaoCompilador(frase);
                //erro = true;
            }
        as.removerEscopo();
        frase += "Fim da compilacao" + "\n";
        if(!msgErro.isEmpty()) throw new ExcecaoCompilador(msgErro);
        /*try {
            token.setOut(frase);
        } catch (IOException ex) {
            Logger.getLogger(AnalisadorSintatico.class.getName()).log(Level.SEVERE, null, ex);
        }*/
    }

    //Regra 2
    public void declaracoes() throws ExcecaoCompilador{
        if(token.equals("declare") ||token.equals("constante") || token.equals("tipo") || token.equals("procedimento") || token.equals("funcao")){
            declarando = true;
            decl_local_global();
            declaracoes();
            declarando = false;
        }
    }

    //Regra 3
    public void decl_local_global() throws ExcecaoCompilador{
        
        if(token.equals("declare") ||token.equals("constante") || token.equals("tipo")){
            declaracao_local();
        }
        else
            declaracao_global();
    }

    //Regra 4
    public void declaracao_local() throws ExcecaoCompilador{
        declarando = true;
        if(token.equals("declare")){
            token.getToken();   
            variavel();
        }else
            if(token.equals("constante")){
                categoria = "constante";
                token.getToken();
                if(token.equals("identificador")){
                    Registro re = new Registro();
                    re.setCadeia(token.getNome());
                    
                    
                    token.getToken();
                    if(token.equals(":")){

                        token.getToken();
                        re.setTipo(token.getNome());
                        tipo_basico();
                        if(token.equals("=")){

                            token.getToken();
                            if(as.verificaTipos(token, re)){
                                re.setValor(token.getNome());
                                valor_constante();
                                as.adicionarSimbolo(re);
                            }else
                                if (!erro){
                                    frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + token.getNome() + "\n";//erro
                                    throw new ExcecaoCompilador(frase);
                                    //erro = true;
                                }
                        }else
                                if (!erro){
                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                                    throw new ExcecaoCompilador(frase);
                                    //erro = true;
                                }
                    }else
                        if (!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                            throw new ExcecaoCompilador(frase);
                        }
                }else
                    if (!erro){
                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                        throw new ExcecaoCompilador(frase);
                    }
            }else
                if(token.equals("tipo")){
                    categoria = "tipo";
                    token.getToken();
                    if(token.equals("identificador")){
                        Registro reg = new Registro();
                        reg.setCadeia(token.getNome());
                        reg.setDeclaraTipo(true);
                        
                        token.getToken();
                        if(token.equals(":")){
                            token.getToken();
                            if(token.equals("registro")){
                                reg.setTipo("registro");
                                reg.setPaiRegistro(numeroPai);
                                as.adicionarSimbolo(reg);
                                tipo();
                            }else{
                                tipo();
                                reg.setTipo(tipoDeclarado);
                                as.adicionarSimbolo(reg);
                            }   
                            
                        }else
                            if (!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if (!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                            throw new ExcecaoCompilador(frase);
                        }
                              
                    categoria = "";
                }
        declarando = false;
    }

    //Regra 5
    public void variavel() throws ExcecaoCompilador{
        identificador();
        mais_ident();
        if(token.equals(":")){
            token.getToken();

            if(token.equals("registro")){
                adicionaSimbolosTabela("registro");
                tipo();
            }else{
                tipo();
                adicionaSimbolosTabela(tipoDeclarado);
            }
            
            listaVariaveis.clear();
        }else
            if (!erro){
                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                throw new ExcecaoCompilador(frase);
            }
    }

    //Regra 6
        String nomeInteiro = new String();
        boolean merda = false;
    public void identificador() throws ExcecaoCompilador{ 
        nomeInteiro = "";
        merda = false;
        if(declarando){ adicionaVarLista();}
        if (parametroFuncao){
            //System.out.println("Away!!!");
            contador++;
        }
        ponteiro_opcional();
            if(token.equals("identificador")){
                nomeInteiro = token.getNome();
                if(declarando){
                    categoria = "var";
                    ultimo.setCadeia(token.getNome());
                    ultimo.setCategoria(categoria);
                }
                System.out.println(as.getSimbolo(token.getNome()));
                if(as.getSimbolo(token.getNome()) != null){
                        paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                }else
                   if(!declarando) merda = true;
                    
                token.getToken();
                outros_ident();
                if(merda)
                        msgErro += "Linha " + token.getLinha() + ": identificador " + nomeInteiro + " nao declarado\n";
                dimensao();             
            }else{
                variavel = false;
                if (!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                    throw new ExcecaoCompilador(frase);
                }
            }
    }

    //Regra 7
    public void ponteiro_opcional() throws ExcecaoCompilador{
        if(token.equals("^")){
            ponteiro = true;
            token.getToken();//Consome token OK
        }else
            ponteiro = false;
    }

    //Regra 8
    public void outros_ident() throws ExcecaoCompilador{
        if(token.equals(".")){
            token.getToken();
            if(token.equals("identificador")){
                if(as.getSimbolo(token.getNome()) == null || !as.getSimbolo(token.getNome()).getFilhoRegistro().equals(paiImediato)){
                    nomeInteiro += "." + token.getNome();
                    merda = true;
                   /* frase = "Linha "+ token.getLinha() +": identificador " + token.getNome() + " nao declarado\n";
                    msgErro += frase;
                     frase += paiImediato + "\n" + as.getSimbolo(token.getNome()).getFilhoRegistro() + "\n";//erro*/
                    //as.printTabela();
                    //throw new ExcecaoCompilador(frase);
                }
                
                if(!atribuindo && !chamadaFuncao){
                    if(nomeTipoVar != null)
                    nomeTipoVar += "." + token.getNome();
                    if(as.getSimbolo(token.getNome()) != null)
                        tipoVar = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                }else{
                    if(as.getSimbolo(token.getNome()) != null)
                        meuTipo = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                }
                
                if(as.getSimbolo(token.getNome()) != null)
                    paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                token.getToken();
                outros_ident();
            }else
                if (!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                    throw new ExcecaoCompilador(frase);
                }
        }
        
    }

    //Regra 9
    public void dimensao() throws ExcecaoCompilador{
        if(token.equals("[")){
            String aux1, aux2;
            boolean aux3;
            dimensao = true;
            aux1 = tipoVar;
            aux2 = meuTipo;
            aux3 = atribuindo;
            System.out.println("ZOOOOOOOOM " + aux1 + "    " + aux2);
            tipoVar = "inteiro";
            atribuindo = true;
            token.getToken();
            exp_aritmetica();
            if(token.equals("]")){
                tipoVar = aux1;
                meuTipo = aux2;
                atribuindo = aux3;
                dimensao = false;
                token.getToken();
                dimensao();
            }else
                 if (!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//erro
                    throw new ExcecaoCompilador(frase);
                }
        }
    }

    //Regra 10
    public void tipo() throws ExcecaoCompilador{
        if(token.equals("registro")){
            registro();
        }else
            tipo_estendido();          
            
    }

    //Regra 11
    public void mais_ident() throws ExcecaoCompilador{
        if(token.equals(",")){
            token.getToken();
            identificador();
            mais_ident();
        }
    }

    //Regra 12
    public void mais_variaveis() throws ExcecaoCompilador{
        if(token.equals("^") || token.equals("identificador")){
            variavel();
            mais_variaveis();
        }
    }

    //Regra 13
    public void tipo_basico() throws ExcecaoCompilador{
        if(token.equals("literal") ||token.equals("inteiro") || token.equals("real") || token.equals("logico"))
            token.getToken();
        else
            if(!erro){
                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                throw new ExcecaoCompilador(frase);
            }
    }

    //Regra 14
    public void tipo_basico_ident() throws ExcecaoCompilador{
        if(token.equals("literal") ||token.equals("inteiro") || token.equals("real") || token.equals("logico")){
            tipoDeclarado = token.getTipo();
            tipo_basico();
        }else
            if(token.equals("identificador")){
                //System.out.println("Hy Joe");
                tipoDeclarado = token.getNome();
                tipoNovo = true;
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 15
    public void tipo_estendido() throws ExcecaoCompilador{
        ponteiro_opcional();
        tipo_basico_ident();
    }

    //Regra 16
    public void valor_constante() throws ExcecaoCompilador{
        if(token.equals("cadeia_literal")||token.equals("numero_inteiro")||token.equals("numero_real") ||token.equals("verdadeiro")||token.equals("falso"))
            token.getToken();
        else
            if(!erro){
                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                throw new ExcecaoCompilador(frase);
            }
    }
    //Regra 17
    public void registro() throws ExcecaoCompilador{
        if(token.equals("registro")){
            token.getToken();
            pre = token.getNome();
            duranteRegistro = true;
            variavel();
            mais_variaveis();
            duranteRegistro = false;
            pre = "";
            Registro.contador++;
            if(token.equals("fim_registro")){
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }else
            if(!erro){
                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                throw new ExcecaoCompilador(frase);
            }
    }

    //Regra 18
    public void declaracao_global() throws ExcecaoCompilador{
        declarando = true;
        if(token.equals("procedimento")){
            categoria = "proc";
            Registro re = new Registro();
            token.getToken();
            if(token.equals("identificador")){
                nomeFuncao = token.getNome();
                re.setCadeia(token.getNome());
                re.setCategoria(categoria);
                token.getToken();
                as.adicionarSimbolo(re);
                as.criarEscopo();
                listaVariaveis.clear();
                as.printTabela();
                parametroFuncao = true;
                if(token.equals("(")){
                    token.getToken();
                        System.out.println("OOOOOOOOOOOOOOOOOOOOOO");
                    parametros_opcional();
                        System.out.println("ZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
                    if(token.equals(")")){
                        parametroFuncao = false;
                        as.printTabela();
                        contador = 0;
                        token.getToken();
                        declaracoes_locais();
                        comandos();
                        if(token.equals("fim_procedimento")){
                            as.removerEscopo();
                            token.getToken();
                        }
                        else
                            if(!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if(!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                            throw new ExcecaoCompilador(frase);
                        }
                }else
                    if(!erro){
                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                        throw new ExcecaoCompilador(frase);
                    }
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase); 
                }
        }else{
            if(token.equals("funcao")){
                String meuNome = new String();
                categoria = "func";
                Registro re = new Registro();
                token.getToken();
                if(token.equals("identificador")){
                    nomeFuncao = token.getNome();
                    meuNome = token.getNome();
                    re.setCadeia(token.getNome());
                    re.setCategoria(categoria);
                    as.adicionarSimbolo(re);
                    as.criarEscopo();
                    listaVariaveis.clear();
                    token.getToken();
                    parametroFuncao = true;
                    if(token.equals("(")){
                        token.getToken();
                        parametros_opcional();
                        if(token.equals(")")){
                            parametroFuncao = false;
                            contador = 0;
                            token.getToken();
                            if(token.equals(":")){
                                token.getToken();
                                tipo_estendido();
                                System.out.println("TTTTTTTTTTTTTTTTTTTTTTTTTTT__________" + meuNome);
                                if(as.getPai().getSimbol(meuNome) != null){
                                    System.out.println("RAAAAAAAAAAAAAAAAAAAAAAAAAAA");
                                    as.getPai().getSimbol(meuNome).setTipo(tipoDeclarado);
                                }
                                declaracoes_locais();
                                comandos();
                                if(token.equals("fim_funcao")){
                                    as.removerEscopo();
                                    if(as.getSimbolo(nomeFuncao) != null)
                                        as.getSimbolo(nomeFuncao).setTipo(tipoDeclarado);
                                    nomeFuncao = "";
                                    tipoDeclarado = "";
                                    token.getToken();
                                }
                                else
                                    if(!erro){
                                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                        throw new ExcecaoCompilador(frase);
                                    }
                            }else
                                 if(!erro){
                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                    throw new ExcecaoCompilador(frase);
                                }
                        }else
                             if(!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if(!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                            throw new ExcecaoCompilador(frase);
                        }
                }else
                    if(!erro){
                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                        throw new ExcecaoCompilador(frase);
                    }
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }
        declarando = false;
    }

    //Regra 19
    public void parametros_opcional() throws ExcecaoCompilador{
        if (token.equals("var") || token.equals("identificador") || token.equals("^"))
           parametro();
    }

    //Regra 20
    public void parametro() throws ExcecaoCompilador{
           var_opcional();
           identificador();
           mais_ident();
           if(token.equals(":")){
               token.getToken();
               tipo_estendido();
               adicionaSimbolosTabela(tipoDeclarado);
               mais_parametros();
          }else
               if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 21
    public void var_opcional() throws ExcecaoCompilador{
        if(token.equals("var"))
            token.getToken();
    }

    //Regra 22
    public void mais_parametros() throws ExcecaoCompilador{
        if(token.equals(",")){
            token.getToken();
            parametro();
        }
    }

    //Regra 23
    public void declaracoes_locais() throws ExcecaoCompilador{
        if(token.equals("declare") ||token.equals("constante") ||token.equals("tipo")){
            declaracao_local();
            declaracoes_locais();
        }
    }

    //Regra 24
    public void corpo() throws ExcecaoCompilador{
            declaracoes_locais();
            comandos();         
    }

    //Regra 25
    public void comandos() throws ExcecaoCompilador{
        if(token.equals("leia") ||token.equals("escreva") || token.equals("se") 
                ||token.equals("caso") ||token.equals("para") ||token.equals("enquanto") 
                ||token.equals("faca") ||token.equals("^") ||token.equals("identificador") ||token.equals("retorne")){
            cmd();
            atribuindo = chamadaFuncao = false;
            comandos();
        }
    }

    //Regra 26
    public void cmd() throws ExcecaoCompilador{
        if(token.equals("leia")){
            token.getToken();
            if(token.equals("(")){
                token.getToken();
                identificador();
                mais_ident();
                if(token.equals(")")){
                    token.getToken();
                }else
                    if(!erro){
                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                        throw new ExcecaoCompilador(frase);
                    }
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }else
            if(token.equals("escreva")){
                token.getToken();
                if(token.equals("(")){
                    token.getToken();
                    boolean aux = passouOp;
                    passouOp = false;
                    expressao();
                    mais_expressao();
                    passouOp = aux;
                    if(token.equals(")")){
                        token.getToken();
                    }else
                        if(!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                            throw new ExcecaoCompilador(frase);
                        }
                }else
                    if(!erro){
                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                        throw new ExcecaoCompilador(frase);
                    }
            }else
                if(token.equals("se")){
                    token.getToken();
                    tipoVar = "logico";
                    atribuindo = true;
                    boolean aux = passouOp;
                    passouOp = false;
                    expressao();
                    atribuindo = false;
                    tipoVar = "";
                    passouOp = aux;
                    if(token.equals("entao")){
                        token.getToken();
                        comandos();
                        senao_opcional();
                        if(token.equals("fim_se")){
                            token.getToken();
                        }else
                            if(!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if(!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                            throw new ExcecaoCompilador(frase);
                        }
                }else
                    if(token.equals("caso")){
                        token.getToken();
                        exp_aritmetica();
                        if(token.equals("seja")){
                            token.getToken();
                            selecao();
                            senao_opcional();
                            if(token.equals("fim_caso")){
                                token.getToken();
                            }else
                                if(!erro){
                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                    throw new ExcecaoCompilador(frase);
                                }
                        }else
                            if(!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if(token.equals("para")){
                            token.getToken();
                            if(token.equals("identificador")){
                                token.getToken();
                                if(token.equals("<-")){
                                    token.getToken();
                                    exp_aritmetica();
                                    if(token.equals("ate")){
                                        token.getToken();
                                        exp_aritmetica();
                                        if(token.equals("faca")){
                                            token.getToken();
                                            comandos();
                                            if(token.equals("fim_para")){
                                                token.getToken();
                                            }else
                                                if(!erro){
                                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                                    throw new ExcecaoCompilador(frase);
                                                }
                                        }else
                                            if(!erro){
                                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                                throw new ExcecaoCompilador(frase);
                                            }
                                    }else
                                        if(!erro){
                                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                            throw new ExcecaoCompilador(frase);
                                        }
                                }else
                                    if(!erro){
                                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                        throw new ExcecaoCompilador(frase);
                                    }
                            }else
                                if(!erro){
                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                    throw new ExcecaoCompilador(frase);
                                }
                        }else
                            if(token.equals("enquanto")){
                                token.getToken();
                                passouOp = false;
                                expressao();
                                if(token.equals("faca")){
                                    token.getToken();
                                    comandos();
                                    if(token.equals("fim_enquanto")){
                                        token.getToken();
                                    }else
                                        if(!erro){
                                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                            throw new ExcecaoCompilador(frase);
                                        }
                                }else
                                    if(!erro){
                                        frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                        throw new ExcecaoCompilador(frase);
                                    }
                            }else
                                if(token.equals("faca")){
                                    token.getToken();
                                    comandos();
                                    if(token.equals("ate")){
                                        token.getToken();
                                        passouOp = false;
                                        expressao();
                                    }else
                                       if(!erro){
                                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                            throw new ExcecaoCompilador(frase);
                                        }
                                }else
                                    if(token.equals("^")){
                                        token.getToken();
                                        if(token.equals("identificador")){
                                            nomeTipoVar = token.getNome();
                                            tipoVar = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                                            tipoVarPonteiro = true;
                                            paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                                            token.getToken();
                                            outros_ident();
                                            dimensao();
                                            if(token.equals("<-")){
                                                atribuindo = true;
                                                token.getToken();
                                                passouOp = false;
                                                expressao();
                                                atribuindo = false;
                                                tipoVarPonteiro = false;
                                            }else
                                                if(!erro){
                                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                                    throw new ExcecaoCompilador(frase);
                                                }
                                        }else
                                            if(!erro){
                                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                                throw new ExcecaoCompilador(frase);
                                            }
                                    }else
                                        if(token.equals("identificador")){
                                            if(!atribuindo){
                                                nomeTipoVar = token.getNome();
                                                tipoVar = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                                            }
                                            paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                                            token.getToken();
                                            if(token.equals("(")) {
                                                chamadaFuncao = true;
                                                nomeFuncao = nomeTipoVar;
                                            }
                                            chamada_atribuicao();
                                            
                                            if(tipoVar != null && tipoVar.equals("logico") && !passouOp  && !tipoParcialExpressao.equals("logico")){
                                                if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                                msgErro += "Linha "+ token.getLinhaAnt() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                                System.out.println("----------------> Tipo -> " + tipoVar  + " Passou op: " + passouOp + " Tipo Parcial: " + tipoParcialExpressao +" <--------------------------");
                                            }
                                            atribuindo =false;
                                            chamadaFuncao = false;
                                        }else
                                            if(token.equals("retorne")){
                                                if(declarando && categoria.equals("func")){
                                                    frase = "Linha "+ token.getLinha() +": comando retorne nao permitido nesse escopo \n";
                                                    msgErro += frase;
                                                    //throw new ExcecaoCompilador(frase);
                                                }
                                                token.getToken();
                                                passouOp = false;
                                                expressao();
                                            }else
                                                if(!erro){
                                                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                                    throw new ExcecaoCompilador(frase);
                                                }
    }

    //Regra 27
    public void mais_expressao() throws ExcecaoCompilador{
        if(token.equals(",")){
            token.getToken();
            contador++;
            expressao();
            mais_expressao();
        }
        contador = 0;
    }

    //Regra 28
    public void senao_opcional() throws ExcecaoCompilador{
        if(token.equals("senao")){
            token.getToken();
            comandos();
        }
    }

    //Regra 29
    public void chamada_atribuicao() throws ExcecaoCompilador{
        if(token.equals("(")){
            token.getToken();
            System.out.println("----------------> " + token.getTipo() + " <--------------" );
            
            expressao();
            
            mais_expressao();
            if(token.equals(")")){
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }else{
            //token.getToken();
            
            outros_ident();
            dimensao();
            if(token.equals("<-")){
                atribuindo = true;    
                token.getToken();
                passouOp = false;
                expressao();
                //verificar aki
            }else{
                atribuindo = false;
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
            }
            atribuindo = false;
        }
    }

    //Regra 30
    public void selecao() throws ExcecaoCompilador{ 
            constantes();
            if(token.equals(":")){
                token.getToken();
                comandos();
                mais_selecao();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 31
    public void mais_selecao() throws ExcecaoCompilador{
        if(token.equals("-") ||token.equals("numero_inteiro")){
            selecao();
        }
       
    }

    //Regra 32
    public void constantes() throws ExcecaoCompilador{
            numero_intervalo();
            mais_constantes();
    }

    //Regra 33
    public void mais_constantes() throws ExcecaoCompilador{
        if(token.equals(",")){
            token.getToken();
            constantes();
        }
    }

    //Regra 34
    public void numero_intervalo() throws ExcecaoCompilador{
            op_unario();
            if(token.equals("numero_inteiro")){
                token.getToken();
                intervalo_opcional();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 35
    public void intervalo_opcional() throws ExcecaoCompilador{
        if(token.equals("..")){
            token.getToken();
            op_unario();
            if(token.equals("numero_inteiro")){
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }
    }

    //Regra 36
    public void op_unario() throws ExcecaoCompilador{
        if(token.equals("-"))
            token.getToken();//OK
    }

    //Regra 37
    public void exp_aritmetica() throws ExcecaoCompilador{
            termo();
            outros_termos();

    }

    //Regra 38
    public void op_multiplicacao() throws ExcecaoCompilador{
        if(token.equals("*")){
            token.getToken();
        }else
            if(token.equals("/")){
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 39
    public void op_adicao() throws ExcecaoCompilador{
        if(token.equals("+")){
            token.getToken();
        }else
            if(token.equals("-")){
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 40
    public void termo() throws ExcecaoCompilador{
            fator();
            outros_fatores();       
    }

    //Regra 41
    public void outros_termos() throws ExcecaoCompilador{
        if(token.equals("+") ||token.equals("-")){
            op_adicao();
            termo();
            outros_termos();
        }
    }

    //Regra 42
    public void fator() throws ExcecaoCompilador{
            parcela();
            outras_parcelas();
    }

    //Regra 43
    public void outros_fatores() throws ExcecaoCompilador{
        if(token.equals("*") ||token.equals("/")){
            
            op_multiplicacao();
            fator();
            outros_fatores();
        }
    }

    //Regra 44
    public void parcela() throws ExcecaoCompilador{
        if(token.equals("-") ||token.equals("^") ||token.equals("identificador") ||token.equals("numero_inteiro") ||token.equals("numero_real") ||token.equals("(")){
            op_unario();
            
            parcela_unario();
        }else
            //if(token.equals("&")){
            
                parcela_nao_unario();
            //}else
              //  frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
    }

    //Regra 45
    public void parcela_unario() throws ExcecaoCompilador{
        if(token.equals("^")){
            token.getToken();
            if(token.equals("identificador")){
               String zas = new String();
               zas = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
               paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
               token.getToken();
               outros_ident();
               if(atribuindo){
                   if(!passouOp){
                       if(!equalComNum(tipoVar, zas)
                            && !tipoVar.equals("logico")){
                            //throw new ExcecaoCompilador
                                    if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                    frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                    msgErro += frase;}
                       else
                       tipoParcialExpressao = zas;
                   }else
                       if(!equalComNum(tipoParcialExpressao,zas) || !tipoVar.equals("logico")){
                           //throw new ExcecaoCompilador
                           if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                           frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                           msgErro += frase;
                       }
               }else
               
               if (chamadaFuncao){
                   if(!passouOp){
                        if(!verArgumento("logico") 
                               && !verArgumento(zas)){
                                //throw new ExcecaoCompilador
                                frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                msgErro += frase;
                        
                        }
                        else
                        tipoParcialExpressao = zas;
                   }else
                       if(!verArgumento("logico") || 
                             !equalComNum(tipoParcialExpressao, zas)){
                                //throw new ExcecaoCompilador
                           frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                           msgErro += frase;
                       }
               }
               dimensao();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    msgErro += frase;
                    //throw new ExcecaoCompilador(frase);
                }
        }else
            
            if(token.equals("identificador")){
                nomeInteiro = "";
                if(as.getSimbolo(token.getNome()) != null){
                    paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                    meuTipo = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                }else{
                    msgErro +=  "Linha "+ token.getLinha() +": identificador " + token.getNome() + " nao declarado\n";
                    paiImediato = "";
                    meuTipo = "";
                }
                String vdd = new String(), nomeZ = new String();
                boolean auxFunc = false, usou = false;
                nomeZ = token.getNome();
                nomeInteiro = token.getNome();
                token.getToken();
                
                if(token.equals("(") || token.equals("[")){
                    vdd = meuTipo;
                    if(token.equals("(")){ 
                            auxFunc = chamadaFuncao;
                            usou = true;
                            chamadaFuncao = true;
                            //if(atribuindo)
                                nomeFuncao = nomeZ;
                    }
                
                }
                chamada_partes();
                if(usou)chamadaFuncao = auxFunc;
                if(vdd != null && !vdd.isEmpty()) meuTipo = vdd;
                if(dimensao){
                       if(passouOp){
                           //throw new ExcecaoCompilador
                           if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                   frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                   msgErro += frase;
                       }else
                           if(!equalComNum("inteiro",meuTipo)){
                               //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                       frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                       msgErro += frase;
                           }
               }else
                if (chamadaFuncao){
                   if(!passouOp){
                        if(!verArgumento("logico") 
                               && !verArgumento(meuTipo)){
                                //throw new ExcecaoCompilador
                                frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                msgErro += frase;
                        }
                        else
                        tipoParcialExpressao = meuTipo;
                   }else
                       if(!verArgumento("logico") || 
                             !equalComNum(tipoParcialExpressao, as.getSimbolo(token.getNome(),token.getLinha()).getTipo())){
                                //throw new ExcecaoCompilador
                            frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                            msgErro += frase;
                       }
               }else
                if(atribuindo){
                       if(!passouOp){
                           if(!equalComNum(tipoVar, meuTipo)
                                && !tipoVar.equals("logico")){
                               as.printTabela();
                                //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinhaAnt() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }
                               
                           tipoParcialExpressao = meuTipo;
                       }else
                           if(!equalComNum(tipoParcialExpressao,meuTipo) || !tipoVar.equals("logico")){
                               //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para +++ " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }
               }
               
               
            }else
                if(token.equals("numero_inteiro") || token.equals("numero_real")){
                    if(atribuindo){
                        if(!passouOp){
                           if(!equalComNum(tipoVar, token.getTipo())
                                && !tipoVar.equals("logico")){
                                //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }
                           else
                           tipoParcialExpressao = token.getTipo();
                       }else
                           if(!equalComNum(tipoParcialExpressao,token.getTipo()) || !tipoVar.equals("logico")){
                              // throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }
                    }else
                        if (chamadaFuncao){
                            if(!passouOp){
                                if(!verArgumento("logico") 
                                    && !verArgumento(token.getTipo())){
                                //throw new ExcecaoCompilador
                                    frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                    msgErro += frase;
                                }
                                else
                        tipoParcialExpressao = token.getTipo();
                   }else
                       if(!verArgumento("logico") || 
                             !equalComNum(tipoParcialExpressao, token.getTipo())){
                                //throw new ExcecaoCompilador
                            frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                            msgErro += frase;
                       }
               }    
                    token.getToken();
                }else
                    if(token.equals("(")){
                        token.getToken();
                        expressao();
                        if(token.equals(")"))
                            token.getToken();
                        else
                            if(!erro){
                                frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                                throw new ExcecaoCompilador(frase);
                            }
                    }else
                        if(!erro){
                            frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                            throw new ExcecaoCompilador(frase);
                        }
    }

    //Regra 46
    public void parcela_nao_unario() throws ExcecaoCompilador{
        if(token.equals("&")){
            token.getToken();
            if(token.equals("identificador")){
                meuTipo = as.getSimbolo(token.getNome(),token.getLinha()).getTipo();
                paiImediato = as.getSimbolo(token.getNome(), token.getLinha()).getPaiRegistro();
                token.getToken();
                outros_ident();
                if(atribuindo){
                       if(!passouOp){
                           if(!equalComNum(tipoVar, meuTipo)
                                && !tipoVar.equals("logico")){
                                //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                msgErro += frase;
                           }
                           else
                           tipoParcialExpressao = meuTipo;
                       }else
                           if(!equalComNum(tipoParcialExpressao,meuTipo) || !tipoVar.equals("logico")){
                               //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }

               }else
               if (chamadaFuncao){
                   if(!passouOp){
                        if(!verArgumento("logico") 
                               && !verArgumento(meuTipo)){
                                //throw new ExcecaoCompilador
                                frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                msgErro += frase;
                        }
                        else
                        tipoParcialExpressao = meuTipo;
                   }else
                       if(!verArgumento("logico") || 
                             !equalComNum(tipoParcialExpressao, as.getSimbolo(token.getNome(),token.getLinha()).getTipo())){
                                //throw new ExcecaoCompilador
                                frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                msgErro += frase;
                       }
               }
                dimensao();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    throw new ExcecaoCompilador(frase);
                }
        }else
            if(token.equals("cadeia_literal")){
                if(atribuindo) {
                     if(!passouOp){
                           if(!equalComNum(tipoVar, "literal")
                                && !tipoVar.equals("logico")){
                                //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                                frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                                msgErro += frase;
                           }
                           else
                           tipoParcialExpressao = "literal";
                       }else
                           if(!equalComNum(tipoParcialExpressao,"literal") || !tipoVar.equals("logico")){
                               //throw new ExcecaoCompilador
                               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
                               frase = "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
                               msgErro += frase;
                           }

               }else
               if (chamadaFuncao){
                   if(!passouOp){
                        if(!verArgumento("logico") 
                               && !verArgumento("literal")){
                                //throw new ExcecaoCompilador
                                frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                                msgErro += frase;
                        }
                        else
                        tipoParcialExpressao = "literal";
                   }else
                       if(!verArgumento("logico") || 
                             !equalComNum(tipoParcialExpressao, "literal")){
                                //throw new ExcecaoCompilador
                               frase = "Linha "+ token.getLinha() +": incompatibilidade de parametros na chamada de " + nomeFuncao + "\n";
                               msgErro += frase;
                       }
               }
                token.getToken();
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    //msgErro += frase;
                    throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 47
    public void outras_parcelas() throws ExcecaoCompilador{
        if(token.equals("%")){
            token.getToken();
            parcela();
            outras_parcelas();
        }
    }

    //Regra 48
    public void chamada_partes() throws ExcecaoCompilador{
        if(token.equals("(")){
            token.getToken();
            chamadaFuncao = true;
            expressao();
            mais_expressao();
            chamadaFuncao = false;
            if(token.equals(")"))
                token.getToken();
            else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    msgErro += frase;
                    //throw new ExcecaoCompilador(frase);
                }
        }else
            if(token.equals(".") || token.equals("[")){
                outros_ident();
                dimensao();
            }
    }

    //Regra 49
    public void exp_relacional() throws ExcecaoCompilador{
            exp_aritmetica();
            op_opcional();
       
    }

    //Regra 50
    public void op_opcional() throws ExcecaoCompilador{
        if(token.equals("=") ||token.equals("<>") ||token.equals(">=") ||token.equals("<=") ||token.equals(">") ||token.equals("<")){
            op_relacional();
            exp_aritmetica();
        }
    }

    //Regra 51
    public void op_relacional() throws ExcecaoCompilador{
        if(token.equals("=")){
           opIgual = true;
           tipoExpressao = "logico";
           passouOp = true;
           token.getToken();
        }else
            if(token.equals("<>") || token.equals(">=") || token.equals("<=") 
                    || token.equals(">") || token.equals("<")){
                opIgual = false;
                tipoExpressao = "logico";
                passouOp = true;
                token.getToken();                
            }else
                if(!erro){
                    frase = "Linha "+ token.getLinha() +": erro sintatico proximo a " + token.getNome() + "\n";//ERRO
                    msgErro += frase;
                    //throw new ExcecaoCompilador(frase);
                }
    }

    //Regra 52
    public void expressao() throws ExcecaoCompilador{
            //boolean aux = passouOp;
            //passouOp = false;
            if(chamadaFuncao)contador++;
            termo_logico();
            outros_termos_logicos();
            //passouOp = aux;
    }

    //Regra 53
    public void op_nao() throws ExcecaoCompilador{
        if(token.equals("nao")){
            tipoExpressao = "logico";
            token.getToken();
        }
    }

    //Regra 54
    public void termo_logico() throws ExcecaoCompilador{
            fator_logico();
            outros_fatores_logicos();
    }

    //Regra 55
    public void outros_termos_logicos() throws ExcecaoCompilador{
        if(token.equals("ou")){
            token.getToken();
            passouOp = false;
            termo_logico();
            outros_termos_logicos();
        }
    }

    //Regra 56
    public void outros_fatores_logicos() throws ExcecaoCompilador{
        if(token.equals("e")){
            token.getToken();
            passouOp = false;
            fator_logico();
            outros_fatores_logicos();
        }
    }

    //Regra 57
    public void fator_logico() throws ExcecaoCompilador{
            op_nao();
            parcela_logica();
      
    }

    //Regra 58
    public void parcela_logica() throws ExcecaoCompilador{
        if(token.equals("verdadeiro") || token.equals("falso")){
           tipoExpressao = "logico";
           if(atribuindo && !tipoVar.equals("logico")){
               if(as.getSimbolo(nomeTipoVar) != null && as.getSimbolo(nomeTipoVar).isPonteiro()) nomeTipoVar = "^" + nomeTipoVar;
               msgErro += "Linha "+ token.getLinha() +": atribuicao nao compativel para " + nomeTipoVar + "\n";
           }
            token.getToken();
        }else
            exp_relacional();
    }
    
    
    public void adicionaVarLista(){
        listaVariaveis.add(new Registro());
        ultimo = listaVariaveis.get(listaVariaveis.size() - 1);
    }
    
    public void adicionaSimbolosTabela(String tipo) throws ExcecaoCompilador{
        for(Registro a :listaVariaveis){
  
            if(!tipo.equals("inteiro") && !tipo.equals("real") && !tipo.equals("logico") 
                    && !tipo.equals("literal") && !tipo.equals("registro") &&
                    as.getSimbolo(tipo) == null)
                msgErro += "Linha " + token.getLinhaAnt() + ": tipo " + tipo + " nao declarado\n";
            
            
                a.setTipo(tipo);
                a.setPonteiro(ponteiro);
                a.setCategoria(categoria);
                if(tipo.equals("registro")){
                    a.setPaiRegistro();
                }

                if(duranteRegistro){
                    a.setFilhoRegistro();
                }



                if(tipoNovo)
                    as.getInformacaoTipo(a, tipo, token.getLinha());
                System.out.println("ANTES -> " + a);
                if (parametroFuncao){
                    System.out.println("RASEEEEENNNNNNGAAAANNNNN~");
                    Registro aux = new Registro(a);
                    aux.setCadeia(nomeFuncao+"_"+a.getTipo()+"_vaiconrinthians_argumento_"+contador);
                    as.getPai().addSimbol(aux.getCadeia(), aux);
                }
                System.out.println("DEPOIS -> " + a);
                as.adicionarSimbolo(a, token.getLinhaAnt());
                System.out.println("SAAAAAAAAAAAAAIIIIIIUUUUUUUUUUU");
                
        }
        

        listaVariaveis.clear();
        ponteiro = false;
        categoria = "";
        tipoNovo = false;
        nomeFuncao = "";
    }
    
    public boolean equalComNum(String a, String b){
        if(a.equals("inteiro") || a.equals("real"))
            return b.equals("inteiro") || b.equals("real") || b.equals("numero_inteiro") || b.equals("numero_real");
        return a.equals(b);
    }
    
    public boolean verArgumento(String b) throws ExcecaoCompilador{
        if(b.equals("inteiro") || b.equals("real") || b.equals("numero_inteiro") || b.equals("numero_real")){
            return  as.getSimbolo(nomeFuncao+"_"+"inteiro" 
                        +"_vaiconrinthians_argumento_"+contador) != null ||
                     as.getSimbolo(nomeFuncao+"_"+"real" 
                        +"_vaiconrinthians_argumento_"+contador) != null;
        }
        if(as.getSimbolo(nomeFuncao+"_"+b 
                        +"_vaiconrinthians_argumento_"+contador) == null)
            System.out.println(nomeFuncao+"_"+b 
                        +"_vaiconrinthians_argumento_"+contador);
        return  as.getSimbolo(nomeFuncao+"_"+b 
                        +"_vaiconrinthians_argumento_"+contador) != null;
    }
}
